const fs = require('fs').promises;
const path = require('path');
const crypto = require('crypto');

/**
 * 抓取内容管理器
 * 负责管理抓取内容的存储和检查
 */
class CaptureManager {
    /**
     * @param {Object} options - 配置选项
     * @param {string} options.baseDir - 基础目录
     */
    constructor(options = {}) {
        this.options = {
            baseDir: path.join(process.cwd(), 'assets', 'captures'),
            ...options
        };
    }

    /**
     * 获取URL的安全文件名
     * @param {string} url - URL
     * @returns {string} 安全的文件名
     */
    getSafeDirName(url) {
        // 使用URL的MD5作为目录名
        return crypto.createHash('md5').update(url).digest('hex');
    }

    /**
     * 初始化存储目录
     * @returns {Promise<void>}
     */
    async initialize() {
        await fs.mkdir(this.options.baseDir, { recursive: true });
    }

    /**
     * 获取捕获内容的目录路径
     * @param {string} url - URL
     * @returns {string} 目录路径
     */
    getCaptureDir(url) {
        return path.join(this.options.baseDir, this.getSafeDirName(url));
    }

    /**
     * 保存抓取内容
     * @param {string} url - 目标URL
     * @param {Object} data - 抓取数据
     */
    async saveCapture(url, data) {
        try {
            // 生成唯一的文件名
            const hash = crypto.createHash('md5').update(url).digest('hex');
            const captureDir = path.join(this.options.baseDir, hash);

            // 确保目录存在
            await fs.mkdir(captureDir, { recursive: true });

            // 构建基础元数据
            const metadata = {
                url,
                captureTime: new Date().toISOString()
            };

            // 动态注入 selectors action 定义的字段
            Object.keys(data).forEach(key => {
                if (key !== 'content') {
                    metadata[key] = data[key] || null;
                }
            });

            // 保存元数据
            const metadataPath = path.join(captureDir, 'metadata.json');
            await fs.writeFile(metadataPath, JSON.stringify(metadata, null, 2), 'utf-8');

            // 保存内容
            if (data.content) {
                const contentPath = path.join(captureDir, 'content.md');
                await fs.writeFile(contentPath, data.content, 'utf-8');
            }

            console.log(`抓取内容已保存到: ${captureDir}`);
            return metadata;
        } catch (error) {
            console.error(`保存抓取内容失败: ${url}`, error);
            return null;
        }
    }

    /**
     * 获取抓取内容
     * @param {string} url - 目标URL
     * @returns {Promise<Object>} 抓取数据
     */
    async getCapture(url) {
        const dirName = this.getSafeDirName(url);
        const captureDir = path.join(this.options.baseDir, dirName);

        try {
            const metadata = JSON.parse(
                await fs.readFile(path.join(captureDir, 'metadata.json'), 'utf8')
            );

            const contentPath = path.join(captureDir, 'content.md');
            if (await fs.access(contentPath).catch(() => false)) {
                metadata.content = await fs.readFile(contentPath, 'utf8');
            }

            return metadata;
        } catch (error) {
            console.error(`获取抓取内容失败: ${url}`, error);
            return null;
        }
    }

    /**
     * 检查URL是否已经抓取过
     * @param {string} url - 目标URL
     * @returns {Promise<boolean>} 是否已抓取
     */
    async isCaptured(url) {
        const dirName = this.getSafeDirName(url);
        const captureDir = path.join(this.options.baseDir, dirName);

        try {
            await fs.access(captureDir);
            return true;
        } catch {
            return false;
        }
    }

    /**
     * 保存资源文件
     * @param {string} url - URL
     * @param {string} filename - 文件名
     * @param {Buffer|string} content - 文件内容
     * @param {string} type - 资源类型 ('resources' | 'screenshots')
     * @returns {Promise<string>} 保存的文件路径
     */
    async saveResource(url, filename, content, type = 'resources') {
        const dirName = this.getSafeDirName(url);
        const captureDir = path.join(this.options.baseDir, dirName);
        const resourceDir = path.join(captureDir, type);
        
        await fs.mkdir(resourceDir, { recursive: true });
        const resourcePath = path.join(resourceDir, filename);
        await fs.writeFile(resourcePath, content);
        return resourcePath;
    }

    /**
     * 设置基础目录
     * @param {string} baseDir - 新的基础目录路径
     */
    setBaseDir(baseDir) {
        this.options.baseDir = baseDir;
        // 确保目录存在
        return fs.mkdir(this.options.baseDir, { recursive: true });
    }
}

module.exports = CaptureManager;
